/*
Flash.h
	
	Controls a MT29F4G01AAADD NAND Flash Device

	Written By Jacob Weiss for Dartmouth Greencube 2013
        VERSION 29 March 2013
*/

#ifndef FLASH_H
#define FLASH_H

#include "Arduino.h" // for byte data type
#include "SPI.h"

enum State 
{
  STATE_NONE, 
  STATE_PROGRAM_LOAD, 
  STATE_READ_FROM_CACHE, 
  STATE_PROGRAM_EXECUTE, 
  STATE_PAGE_READ,
  STATE_BLOCK_ERASE
};

enum OperationStatus
{
	OS_IN_PROGRESS = 0,
	OS_SUCCESS,
	OS_ERASE_FAIL,
	OS_WRITE_FAIL
};

enum FlashCommand 
{
  BLOCK_ERASE = 0xd8, 
  GET_FEATURE = 0x0f, 
  PAGE_READ = 0x13, 
  PROGRAM_EXECUTE = 0x10, 
  PROGRAM_LOAD = 0x02, 
  PROGRAM_LOAD_RANDOM_DATA = 0x84,
  READ_FROM_CACHE = 0x03,
  READ_FROM_CACHE_2 = 0x3b,
  READ_FROM_CACHE_4 = 0x6b,
  READ_ID = 0x9f,
  RESET = 0xff,
  SET_FEATURE = 0x1f,
  WRITE_DISABLE = 0x04,
  WRITE_ENABLE = 0x06,
  DUMMY_BYTE = 42
};

enum FeatureByte
{
  FEATURE_BLOCK_LOCK = 0xA0,
  FEATURE_OTP = 0xB0,
  FEATURE_STATUS = 0xC0
};

enum BlockLock
{
  LOCK_ALL = 0x07,
  LOCK_2 = 0x06,
  LOCK_4 = 0x05,
  LOCK_8 = 0x04,
  LOCK_16 = 0x03,
  LOCK_32 = 0x02,
  LOCK_64 = 0x01,
  LOCK_NONE = 0x00
};

class Flash
{	
  public:
    Flash();
    	
    void writeBytes(byte* bytes, int length);
	void cacheToArray();	
	void dumpArray(uint32_t startAddress, uint32_t endAddress, int amount);	
    
    uint16_t readID();
    
  private:		
    State state;
		
	uint32_t currentPage;
    
	int slaveSelectPin;
	int writeProtectPin;
	int holdPin;
	
	void blockUntilFinished();
		
    void writeEnable();
    
    void programLoadStart(int plane, uint16_t column);
    void programLoad(byte data);   
    void programLoadEnd();  

    void readFromCacheStart(int plane, uint16_t column);   
    int readFromCache();
    void readFromCacheEnd();

    void pageRead(uint32_t address);
    void programExecute(uint32_t address);  

	void blockErase(uint32_t address);

    boolean changeState(State changeTo);

    void setLocks(BlockLock data);
	
	void updateEepromAddress(uint32_t address);
	uint32_t getEepromAddress();
	
	int getPlane(uint32_t address);
	int getCurrentPlane();
	
    void reset();   
    OperationStatus  operationStatus();
    int  getFeature(FeatureByte address);   
	
	void csh();
	void csl();
};

#endif
